package com.iot.core.base;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.qpid.jms.JmsConnection;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import java.text.MessageFormat;
import java.util.Hashtable;

@Data
@Slf4j
public class IotDefaultIConnection implements IotConnection {
    private final IotEnvironment env;

    public IotDefaultIConnection(IotEnvironment env) {
        this.env = env;
    }

    private Context context;
    private Session session;
    private MessageConsumer messageConsumer;
    private Connection connection;

    @Override
    public void connect() {
        try {
            // 构造连接参数
            long timestamp = System.currentTimeMillis();
            String connectUrl = MessageFormat.format("failover:(amqps://{0}.iot-amqp.{1}.aliyuncs.com:5671?amqp.idleTimeout=80000)?failover.reconnectDelay=30",
                    env.getIotConnectParam().getUid(), env.getIotConnectParam().getRegionId());
            String username = MessageFormat.format("{0}-{1}|authMode=aksign,signMethod={2},timestamp={3},authId={4},iotInstanceId={5},consumerGroupId={6}|",
                    env.getIotConnectParam().getClientId(), env.getConnectCount(), env.getSignMethod(), String.valueOf(timestamp),
                    env.getIotConnectParam().getAccessKey(), env.getIotConnectParam().getIotInstanceId(), env.getIotConnectParam().getConsumerGroupId());
            String signContent = MessageFormat.format("authId={0}&timestamp={1}", env.getIotConnectParam().getAccessKey(), String.valueOf(timestamp));
            String password = doSign(signContent, env.getIotConnectParam().getAccessSecret(), env.getSignMethod());

            //创建连接部分
            Hashtable<String, String> hashtable = new Hashtable<>(4);
            hashtable.put("connectionfactory.SBCF", connectUrl);
            hashtable.put("queue.QUEUE", "default");
            hashtable.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.qpid.jms.jndi.JmsInitialContextFactory");
            context = new InitialContext(hashtable);
            ConnectionFactory cf = (ConnectionFactory) context.lookup("SBCF");
            Destination queue = (Destination) context.lookup("QUEUE");
            connection = cf.createConnection(username, password);
            ((JmsConnection) connection).addConnectionListener(env.getConnectionListener());
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            connection.start();
            messageConsumer = session.createConsumer(queue);
            messageConsumer.setMessageListener(env.getMessageListener());
        } catch (Exception e) {
            log.error("IOT平台连接失败:", e);
            throw new RuntimeException(e);
        }

    }

    @Override
    public void disconnect() {
        try {
            if (connection != null) {
                connection.close();
            }
            if (context != null) {
                context.close();
            }
            if (session != null) {
                session.close();
            }
            if (messageConsumer != null) {
                messageConsumer.close();
            }
        } catch (Throwable ignored) {
        }
    }

    private String doSign(String signContent, String secret, String signMethod) throws Exception {
        SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(), signMethod);
        Mac mac = Mac.getInstance(signMethod);
        mac.init(signingKey);
        byte[] rawHmac = mac.doFinal(signContent.getBytes());
        return Base64.encodeBase64String(rawHmac);
    }
}
